/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Delta;

import Exceptions.NoLayersException;
import Jama.Matrix;
import java.util.ArrayList;

/**
 *
 * @author Ahmet
 */
public class Laminaat {

    private String name;
    
    //A,B,D, ThermQ1 & ThermQ2 matrices
    private boolean matrices1Calculated;
    //a,b,d en comp matrices
    private boolean matrices2Calculated;
    //Strain-matrix (Strain = comp*[-ThermQ1;-ThermQ2] (ThermQ1 en 2 onder elkaar))
    private boolean strainCalculated;
    
    //waardes laminaat
    private double E1, E2, Mu12, Mu21, G12, Rho;
    
    //extra waardes
    private double E3, G23, G31, Mu23, Mu31, A1, A2, A3;
    
    // A: reksijfheidsmatrix (3x3)
    private Matrix A;
    // B: koppelstijfheidsmatrix (3x3)
    private Matrix B;
    // D: buigstijfheidsmatrix (3x3)
    private Matrix D;
    // Thermische uitzetting matrix (1x3)
    private Matrix ThermQ1; 
    // Thermische uitzetting matrix (1x3)
    private Matrix ThermQ2;
    // Matrix of strains due to thermal loads
    private Matrix Strain;
    // Nt
    private Matrix Nt;
    // Mt
    private Matrix Mt;
    
    private Matrix ABD;
    private Matrix a;
    private Matrix b;
    private Matrix d;
    private Matrix abd;
    private Matrix comp;
    
    public ArrayList<Layer> layers;

    public Laminaat() {
        layers = new ArrayList<>();
        matrices1Calculated = false;
        matrices2Calculated = false;
        strainCalculated = false;
    }

    public boolean addLayer(Layer layer) {
        if (layers != null) {
            layers.add(layer);
            return true;
        }
        return false;
    }

    public boolean removeLayer(Layer layer) {
        if (checkLayersBiggerThanZero()) {
            for (Layer l : layers) {
                if (l == layer) {
                    layers.remove(l);
                    return true;
                }
            }
        }
        return false;
    }

    public double calculateMidPlane() {
        if (checkLayersBiggerThanZero()) {
            return (calculateTotalHeight() / 2);
        } else {
            return -1;
        }
    }

    public double calculateTotalHeight() {
        if (checkLayersBiggerThanZero()) {
            double total = 0;
            for (Layer l : layers) {
                total += l.getThickness();
            }
            return total;
        }
        return -1;
    }

    public boolean setLayerHeights() {
        if (checkLayersBiggerThanZero()) {
            double midPlane = calculateMidPlane();
            double total = 0;
            for (Layer l : layers) {
                l.setHeightBottom((total - midPlane));
                total += l.getThickness();
                l.setHeightTop((total - midPlane));
                //l.setHeightBottom(total);
                //l.setHeightTop(total);
            }
            return true;
        }
        return false;
    }

    public boolean checkLayersBiggerThanZero() {
        try {
            if (layers != null) {
                if (layers.size() > 0) {
                    return true;
                }
            }
            throw new NoLayersException("There are no layers yet");
        } catch (NoLayersException e) {
        }
        return false;
    }

    //A,B,D, ThermQ1 & ThermQ2 matrices
    public void calculateMatrices1() {

        if (checkLayersBiggerThanZero()) {
            Matrix A = new Matrix(3, 3);
            Matrix B = new Matrix(3, 3);
            Matrix D = new Matrix(3, 3);
            for (Layer l : layers) {
                double top = l.getHeightTop();
                double bottom = l.getHeightBottom();
                A = A.plus((l.getQt().times(top - bottom)));
                B = B.plus(l.getQt().times(0.5).times((Math.pow(top, 2)) - (Math.pow(bottom, 2))));
                D = D.plus(l.getQt().times((1 / 3)).times((Math.pow(top, 3)) - (Math.pow(bottom, 3))));
                Lamel lamel = l.getLamel();
                Matrix Q = lamel.getQ1();
                Matrix Qa = lamel.getQA();
                Matrix Qt = l.getQt();
                Matrix Qat = l.getTinv().times(Qa);
                ThermQ1 = ThermQ1.plus(Qt.times(Qat).times(top-bottom));
                ThermQ2 = ThermQ2.plus((Qt.times(Qat).times(Math.pow(top, 2)-Math.pow(bottom, 2))).times(0.5));
            }
            this.A = A;
            this.B = B;
            this.D = D;
            matrices1Calculated = true;
        }
    }
    
    //Compliantiematrices a,b,d en comp
    public void calculateMatrices2() {
        if (!matrices1Calculated) calculateMatrices1();
        Matrix Ainv = A.inverse();
        Matrix Dinv = D.inverse();
        
        a = (A.minus((B.times(Dinv).times(B)))).inverse();
        b = a.uminus().times(B).times(Dinv);
        d = (D.minus((B.times(Ainv).times(B)))).inverse();
        
        //TODO: coordinaten overgenomen uit oude code, controleren
        comp = new Matrix(6, 6);
        comp.setMatrix(0, 2, 0, 2, a);
        comp.setMatrix(3, 5, 0, 2, b);
        comp.setMatrix(0, 2, 3, 5, b);
        comp.setMatrix(3, 5, 3, 5, d);
        
        matrices2Calculated = true;
    }
    
    public void calculateStrain() {
        //TODO: NM testen
        if (!matrices2Calculated) calculateMatrices2();
        Matrix N = ThermQ1.uminus();
        Matrix M = ThermQ2.uminus();
        int columns = N.getColumnDimension();
        if (M.getColumnDimension() > columns) columns = M.getColumnDimension();
        int rows = (M.getRowDimension() + N.getRowDimension());
        Matrix NM = new Matrix(rows,columns);
        NM.setMatrix(0, N.getRowDimension()-1, 0, N.getColumnDimension()-1, N);
        NM.setMatrix(N.getRowDimension(), NM.getRowDimension()-1, N.getColumnDimension(), NM.getColumnDimension()-1, M);
        Strain = comp.times(NM);
        //TODO: Is Nt wel N? & Mt = M?
        Nt = N;
        Mt = M;
        strainCalculated = true;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMatrices1Calculated() {
        return matrices1Calculated;
    }

    public void setMatrices1Calculated(boolean matrices1Calculated) {
        this.matrices1Calculated = matrices1Calculated;
    }

    public boolean isMatrices2Calculated() {
        return matrices2Calculated;
    }

    public void setMatrices2Calculated(boolean matrices2Calculated) {
        this.matrices2Calculated = matrices2Calculated;
    }
    
    public boolean isStrainCalculated() {
        return strainCalculated;
    }

    public void setStrainCalculated(boolean strainCalculated) {
        this.strainCalculated = strainCalculated;
    }

    public Matrix getA() {
        if (!matrices1Calculated) calculateMatrices1();
        return A;
    }

    public void setA(Matrix A) {
        this.A = A;
    }

    public Matrix getB() {
        if (!matrices1Calculated) calculateMatrices1();
        return B;
    }

    public void setB(Matrix B) {
        this.B = B;
    }

    public Matrix getD() {
        if (!matrices1Calculated) calculateMatrices1();
        return D;
    }

    public void setD(Matrix D) {
        this.D = D;
    }

    public double getE1() {
        
        if (E1 == 0)
        {
            if (!matrices2Calculated) calculateMatrices2();
            E1 = 1 / (a.get(0, 0) * calculateTotalHeight());
            return E1;
        }
        else
        return E1;
    }

    public void setE1(double E1) {
        this.E1 = E1;
    }

    public double getE2() {
        if (E2 == 0)
        {
            if (!matrices2Calculated) calculateMatrices2();
            E2 = 1 / (a.get(1, 1) * calculateTotalHeight());
            return E2;
        }
        else
        return E2;
    }

    public void setE2(double E2) {
        this.E2 = E2;
    }

    public double getG12() {
        if (G12 == 0)
        {
            if (!matrices2Calculated) calculateMatrices2();
            G12 = 1 / (a.get(2,2) * calculateTotalHeight());
            return G12;
        }
        else
        return G12;
    }

    public void setG12(double G12) {
        this.G12 = G12;
    }

    public double getMu12() {
        if (Mu12 == 0)
        {
            if (!matrices2Calculated) calculateMatrices2();
            Mu12 = -(a.get(1, 0))/a.get(0,0);
            return Mu12;
        }
        else
        return Mu12;
    }

    public void setMu12(double Mu12) {
        this.Mu12 = Mu12;
    }

    public double getMu21() {
        if (Mu21 == 0)
        {
            if (!matrices2Calculated) calculateMatrices2();
            Mu21 = -(a.get(1, 0))/a.get(1,1);
            return Mu21;
        }
        else
        return Mu21;
    }

    public void setMu21(double Mu21) {
        this.Mu21 = Mu21;
    }
    
    public double getRho() {
        double dikte = 0;
        if (checkLayersBiggerThanZero())
        {
            for (Layer lay : layers)
            {
                dikte+= (lay.getThickness() * lay.getLamel().getRhol());
            }
        }
        return dikte;
    }

    public double getA1() {
        if (A1 == 0)
        {
            if (!strainCalculated) calculateStrain();
            A1 = Strain.get(0, 0);
        }
        return A1;
    }

    public double getA2() {
        if (A2 == 0)
        {
            if (!strainCalculated) calculateStrain();
            A2 = Strain.get(1, 0);
        }
        return A2;
    }

    public double getA3() {
        if (A3 == 0)
        {
            checkLayersBiggerThanZero();
            double top = 0;
            double bottom = 0;
            for (Layer l : layers) {
                double dikte = l.getThickness();
                top += (dikte * l.getLamel().getAlphaT());
                bottom += dikte;
            }
            A3 = (top/bottom);
        }
        return A3;
    }

    public double getE3() {
        if (E3 == 0)
        {
            checkLayersBiggerThanZero();
            double top = 0;
            double bottom = 0;
            for (Layer l : layers) {
                double dikte = l.getThickness();
                top += (dikte * l.getLamel().getEt());
                bottom += dikte;
            }
            E3 = (top/bottom);
        }
        return E3;
    }

    public double getG23() {
        if (G23 == 0)
        {
            checkLayersBiggerThanZero();
            double top = 0;
            double bottom = 0;
            for (Layer l : layers) {
                double dikte = l.getThickness();
                top += (dikte * l.getLamel().getGlt());
                bottom += dikte;
            }
            G23 = (top/bottom);
        }
        return G23;
    }

    public double getG31() {
        if (G31 == 0)
        {
            G31 = getG23();
        }
        return G31;
    }

    public double getMu23() {
        if (Mu23 == 0)
        {
            checkLayersBiggerThanZero();
            double top = 0;
            double bottom = 0;
            for (Layer l : layers) {
                double dikte = l.getThickness();
                top += (dikte * l.getLamel().getMult());
                bottom += dikte;
            }
            Mu23 = (top/bottom);
        }
        return Mu23;
    }

    public double getMu31() {
        if (Mu31 == 0)
        {
            Mu31 = getMu23();
        }
        return Mu31;
    }
    
    
    public Matrix getMt() {
        if (!strainCalculated) calculateStrain();
        return Mt;
    }

    public Matrix getNt() {
        if (!strainCalculated) calculateStrain();
        return Nt;
    }

    @Override
    public String toString() {
        return name;
    }
}
